﻿using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows.Controls;
using System.Windows.Documents;

using VSTalk.Engine.Core.EnvironmentManagers.UI;
using VSTalk.Engine.Core.Feed;
using VSTalk.Engine.Core.History;
using VSTalk.Engine.ViewModel.Messenger.ThreadRenderer;
using VSTalk.Engine.ViewModel.Messenger.ThreadRenderer.Command;
using VSTalk.Model;
using VSTalk.Tools;

using agsXMPP;

namespace VSTalk.Engine.ViewModel.History
{
    public class HistoryExplorerViewModel : IHistoryVisitor, INotifyPropertyChanged, IListener
    {
        private static IHistoryService HistoryService
        {
            get { return AppServices.Get<IHistoryService>(); }
        }

        private static IWindowManager WindowManager
        {
            get { return AppServices.Get<IWindowManager>(); }
        }

        private static IThemeManager ThemeManager
        {
            get { return WindowManager.ThemeManager; }
        }

        private BaseHistoryItem _selectedItem;
        
        private readonly Client _client;

        private ConversationThread _thread;

        private ISubscription _selectedUnit;

        private ISubscription _themeUnit;

        public Jid With { get; set; }
        public RichTextBox HistoryMessages { get; set; }
        public ObservableCollection<HistoryView> HistoryView { get; set; }

        public BaseHistoryItem SelectedItem
        {
            get { return _selectedItem; }
            set
            {
                if (Equals(value, _selectedItem)) return;
                _selectedItem = value;
                PropertyChanged.Notify(() => SelectedItem);
            }
        }

        public HistoryExplorerViewModel(Client client, Jid with)
        {
            _client = client;
            var history = LoadHistory(client, with);
            With = with;
            HistoryView = new ObservableCollection<HistoryView>();

            HistoryMessages = new RichTextBox(new FlowDocument());
            HistoryMessages.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
            HistoryMessages.Background = System.Windows.Media.Brushes.Transparent;
            HistoryMessages.IsReadOnly = true;

            BuildView(history);
            SetTheme(ThemeManager.ActiveTheme);
        }

        private void ThemeChanged(IThemeManager sender)
        {
            SetTheme(ThemeManager.ActiveTheme);
        }

        private void SetTheme(ThemeMode activeTheme)
        {
            HistoryMessages.Document.Foreground = activeTheme == ThemeMode.Dark
                ? System.Windows.Media.Brushes.White
                : System.Windows.Media.Brushes.Black;
        }


        private static List<IMessage> LoadHistory(Client client, Jid with)
        {
            return HistoryService.Read(client.Id, with)
                    .Where(message => !string.IsNullOrEmpty(message.XmppMessage.Body))
                    .ToList();
        }

        private void BuildView(List<IMessage> history)
        {
            var monthGroups = history.OrderByDescending(note => note.Date)
                    .GroupBy(key => key.Date.ToString("MMMM yyyy"));
            foreach (var monthGroup in monthGroups)
            {
                HistoryView.Add(new HistoryView
                {
                    Month = monthGroup.Key,
                    ActiveDates = new ObservableCollection<DayMessageView>(
                            monthGroup.GroupBy(key => key.Date.ToShortDateString())
                                    .Select(dayGroup => new DayMessageView
                                    {
                                        Day = dayGroup.Key,
                                        Messages = new ObservableCollection<IMessage>(dayGroup),
                                    }))
                });
            }
        }

        private void HandleChange()
        {
            if (SelectedItem == null) return;
            SelectedItem.Visit(this);
        }

        private ConversationThread CreateThread(FlowDocument document)
        {
            _thread = new ConversationThread(document);
            return _thread;
        }

        public void Visit(HistoryView view)
        {
            //nothing
        }

        public void Visit(DayMessageView view)
        {
            HistoryMessages.BeginChange();
            HistoryMessages.Document.Blocks.Clear();
            var entityThread = CreateThread(HistoryMessages.Document);
            view.Messages.Each(message =>
            {
                var command = new RenderXmppMessage(entityThread.Model, message);
                command.Execute();
            });
            HistoryMessages.EndChange();
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public void StartListen()
        {
            _selectedUnit = this.SubscribeToChange(() => SelectedItem, sender => HandleChange());
            _themeUnit = ThemeManager.SubscribeToChange(() => ThemeManager.ActiveTheme, ThemeChanged);

        }

        public void StopListen()
        {
            _themeUnit.Unsubscribe();
            _selectedUnit.Unsubscribe();
        }
    }
}